﻿using Se.Data;
using Se.Thread;
using System;
using System.Collections.Generic;

namespace Se.Model.Data
{
    /// <summary>
    /// 数据模型基类
    /// </summary>
    public abstract class DataEntityBase
    {
        /// <summary>
        /// newId是否设置ID
        /// </summary>
        /// <param name="saveType"></param>
        /// <param name="loadType"></param>
        /// <param name="newId"></param>
        public DataEntityBase(DBSaveType saveType, DBLoadType loadType, bool newId = true)
        {
            this.SaveType = saveType;
            this.LoadType = loadType;
            if (newId)
                this.ID = DataEntityIDGenerator.NewGenerateID(GetType());
        }

        /// <summary>
        /// 供模板使用的默认构造函数
        /// </summary>
        public DataEntityBase()
        {
            this.IsDirty = true;
            this.SaveType = DBSaveType.Insert;
        }

        /// <summary>
        /// 是否改变过（是否需要执行存库）
        /// </summary>
        public bool IsDirty { get; set; }

        /// <summary>
        /// 存库方式
        /// </summary>
        public DBSaveType SaveType { get; set; }
        /// <summary>
        /// 加载方式
        /// </summary>
        public DBLoadType LoadType { get; set; }
        /// <summary>
        /// 上次数据变化改变时间
        /// </summary>
        public DateTime LastChangeTime { get; set; }
        /// <summary>
        /// 上次从数据库中加载时间
        /// </summary>
        public DateTime LastLoadTime { get; set; }

        /// <summary>
        /// 是否在DB仓库中
        /// </summary>
        public bool IsInFactory { get; set; }

        /// <summary>
        /// ID
        /// </summary>
        [EntityField("ID", IsKey = true, DbType = ColumnDbType.Long)]
        public long ID { get; set; }

        /// <summary>
        /// 是否已经删除
        /// </summary>
        public bool IsDeleted { get; set; }

        /// <summary>
        /// 加载数据以前执行
        /// </summary>
        public virtual void PreLoadData()
        { }
        /// <summary>
        /// 加载数据以后执行
        /// </summary>
        public virtual void AfterLoadData()
        {

        }

        /// <summary>
        /// 保存数据以前执行
        /// </summary>
        public virtual void PreSaveData()
        { }
        /// <summary>
        /// 保存数据以后执行
        /// </summary>
        public virtual void AfterSaveData()
        { }

        public virtual void Save<T>() where T : DataEntityBase
        {
            this.LastChangeTime = DateTime.Now;
            DataEntityFactory.SaveEntity(this);
        }

        public virtual void Delete<T>()
        {
            this.IsDeleted = true;
            DataEntityFactory.SaveEntity(this);
        }
    }

    /// <summary>
    /// DataEntityID生成器
    /// </summary>
    internal static class DataEntityIDGenerator
    {

        /// <summary>
        /// 静态构造，只在第一次调用静态成员或者第一次初始化类的时候调用
        /// </summary>
        static DataEntityIDGenerator()
        {
            if (IdGenerators == null)
            {
                IdGenerators = new Dictionary<string, SerialIdGenerator>();
            }
        }

        /// <summary>
        /// Id生成器
        /// </summary>
        public static Dictionary<string, SerialIdGenerator> IdGenerators { get; set; }

        /// <summary>
        /// 添加Id生成器
        /// </summary>
        /// <param name="typeName"></param>
        /// <param name="minSerial"></param>
        public static void AddIdGenerator(string typeName, long minSerial)
        {
            var idGenerator = new SerialIdGenerator(minSerial);
            DataEntityIDGenerator.IdGenerators.Add(typeName, idGenerator);
        }

        /// <summary>
        /// 生成新的Id
        /// </summary>
        /// <returns></returns>
        internal static long NewGenerateID(Type type)
        {
            var generator = GetIDGenerator(type);
            var newId = generator.NextSerial();

            return newId;
        }

        /// <summary>
        /// 获取Id生成器
        /// </summary>
        /// <returns></returns>
        private static SerialIdGenerator GetIDGenerator(Type type)
        {
            SerialIdGenerator generator;
            var typeName = type.Name;
            if (!DataEntityIDGenerator.IdGenerators.ContainsKey(typeName))
            {
                AddIdGenerator(typeName, 1);
            }
            generator = DataEntityIDGenerator.IdGenerators[typeName];

            return generator;
        }

    }

}
